#include<iostream>
#include<functional>
using namespace std;

namespace Wang
{

template<class T>
class unique_ptr
{
    T* _p;
public:
    unique_ptr(T* p = nullptr)
        :_p(p)
    {}
    ~unique_ptr() 
    {
        delete _p;
        _p = nullptr;
    }
    unique_ptr(const unique_ptr& p) = delete;
    unique_ptr& operator=(const unique_ptr& p) = delete;
    unique_ptr(unique_ptr&& p)
    {
        std::swap(_p, p._p);
    }
    unique_ptr& operator=(unique_ptr&& p)
    {
        std::swap(_p, p._p);
    }
    T& operator* () { return *_p; }
    T* operator-> () { return _p; }
};


// make_share 会把指向的资源与计数变量绑在一起，减少内存碎片

template<class T>
class shared_ptr
{
    T* _p;
    int* _pcnt;     // 指向计数器
    function<void(T*)> _del;
public:
    shared_ptr(T* p = nullptr)
        :_p(p)
        ,_pcnt(new int(1))
        ,_del([](T* p){ delete p; })
    {}

    template<class D>
    shared_ptr(T* p, D del)
        :_p(p)
        ,_pcnt(new int(1))
        ,_del(del)
    {}

    ~shared_ptr() { release(); }
    void release()
    {
        (*_pcnt)--;
        if(*_pcnt == 0)
        {
            // delete _p;
            _del(_p);
            delete _pcnt;
            _p = nullptr;
            _pcnt = nullptr;
        }
    }
    shared_ptr(const shared_ptr& sp)
        :_p(sp._p)
        ,_pcnt(sp._pcnt)
        ,_del(sp._del)
    {
        (*_pcnt)++;
    }
    void swap(shared_ptr& t)
    {
        std::swap(_p, t._p);
        std::swap(_pcnt, t._pcnt);
    }
    shared_ptr& operator= (const shared_ptr& sp)
    {
        // if(this == &sp) return *this;
        if(_p == sp._p) return *this;
        shared_ptr tmp(sp);
        swap(tmp);
        return *this;
    }
    T& operator* () { return *_p; }
    T* operator-> () { return _p; }
    T* get() { return _p; }
    int use_count() { return *_pcnt; }
};

} // namespace Wang